#include "libGeoutils/tool/normalize_tool.h"

template<class T, class U>
geo::tool::Normalizer<T, U>::Normalizer()
{
}

template<class T, class U>
geo::tool::Normalizer<T, U>::~Normalizer()
{
}

template<class T, class U>
void geo::tool::Normalizer<T, U>::normalizeVector(const std::vector<T>& in_vec, std::vector<U>& out_vec, U new_min, U new_max) const
{
	if (in_vec.empty()) {
		out_vec.clear();
		return;
	}
	T old_min = in_vec[0];
	T old_max = in_vec[0];
	for (const auto& val : in_vec) {
		if (val < old_min) {
			old_min = val;
		}
		if (val > old_max) {
			old_max = val;
		}
	}
	if (old_min == old_max) {
		out_vec.resize(in_vec.size(), static_cast<U>(new_min));
		return;
	}
	out_vec.resize(in_vec.size());
	for (size_t i = 0; i < in_vec.size(); ++i) {
		out_vec[i] = static_cast<U>(((in_vec[i] - old_min) / (old_max - old_min)) * (new_max - new_min) + new_min);
	}
}

template<class T, class U>
void geo::tool::Normalizer<T, U>::limitVectorMinMax(const std::vector<T>& in_vec, std::vector<U>& out_vec, U new_min, U new_max) const
{
	if (new_max < new_min) {
		std::swap(new_min, new_max);
	}

	out_vec.resize(in_vec.size());

	for (size_t i = 0; i < in_vec.size(); ++i) 
	{
		if (in_vec[i] < new_min) {
			out_vec[i] = new_min;
		}
		else if (in_vec[i] > new_max) {
			out_vec[i] = new_max;
		}
		else {
			out_vec[i] = in_vec[i];
		}
	}
}

template class GEOUTILS_EXPORT geo::tool::Normalizer<float, float>;
template class GEOUTILS_EXPORT geo::tool::Normalizer<double, double>;
template class GEOUTILS_EXPORT geo::tool::Normalizer<float, double>;
template class GEOUTILS_EXPORT geo::tool::Normalizer<double, float>;